home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / wterm.arc / WTERM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-11-20  |  15.6 KB  |  485 lines

  1. /*
  2.  * WTERM - A terminal program within a window
  3.  *         "Stripped" Version
  4.  *         by Matt Kimmel, 1987
  5.  *
  6.  * This is this stripped version of Window Term, a terminal program
  7.  * inside a window.  The stripped version is considerably smaller
  8.  * and slightly faster than the Full version.  However, it doesn't have
  9.  * any of the extra functions that the Full version has.  In the Stripped
  10.  * version, you must use a seperate program to set the RS232 parameters.
  11.  *
  12.  * This code should be fairly portable.  I have used calloc() instead
  13.  * of Malloc() because it initializes the reserved space to zeroes.
  14.  * This is a standard K&R function, so it should be implemented in
  15.  * all the ST compilers.
  16.  *
  17.  * The font size may be toggled between the normal font and "Icon"
  18.  * size with ALT-F.  If you press ALT-S, a CTRL-S is sent, and the
  19.  * program won't accept any characters until you press ALT-S again,
  20.  * at which time a CTRL-Q is sent and output is resumed.
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <gemdefs.h>
  25. #include <osbind.h>
  26.  
  27. /* defines for window gadgets */
  28. #define NAME 0x0001
  29. #define CLOSE 0x0002
  30. #define FULL 0x0004
  31. #define MOVE 0x0008
  32. #define SIZE 0x0020
  33.  
  34. /* Macros to turn the mouse on and off */
  35. #define MOUSE_ON graf_mouse(257,&j)
  36. #define MOUSE_OFF graf_mouse(256,&j);
  37.  
  38. /* The size to set the RS232 buffer to */
  39. #define BUFFER_SIZE 8192
  40.  
  41. /* Structure returned by Iorec() */
  42. typedef struct {
  43.   char *ibuf;
  44.   int ibufsiz;
  45.   int ibufhd;
  46.   int ibuftl;
  47.   int ibuflow;
  48.   int ibufhi;
  49.   } IORECORD;
  50.  
  51. /* Standard VDI variables */
  52. int contrl[12], intin[128],ptsin[128],intout[128],ptsout[128];
  53. int w_handle, handle, workin[11], workout[57];
  54. int x,y,w,h;  /* Position of window */
  55. int j;  /* General-purpose junk variable */
  56. int nx, ny; /* X,Y coordinates of next character to be output */
  57. int tx, ty, tw, th; /* Size of the work area of the window */
  58. int hsize, vsize; /* Horizontal and vertical size of characters */
  59. int apid, menuid; /* Application and Menu IDs */
  60. char rs232buf[BUFFER_SIZE]; /* RS232 Buffer */
  61.  
  62. main()
  63. {
  64.   int j; /* Junk variable */
  65.   int msg[8]; /* Message buffer for evnt_mesag */
  66.  
  67.   apid = appl_init();  /* Initialize our application */
  68.   menuid = menu_register(apid,"  Window Term"); /* Register in Desk menu */
  69.   handle = graf_handle(&j,&j,&j,&j); /* Get handle of the screen */
  70.   for(j=0;j++<=9;workin[j]=1);  /* Set up workin array */
  71.   workin[10] = 2;
  72.   v_opnvwk(workin,&handle,workout); /* Open virtual workstation */
  73.   vst_alignment(handle,0,5,&j,&j); /* Set text alignment so that
  74.                                       so that the y coordinate is
  75.                                       the top line of a character
  76.                                       with v_gtext */
  77.   hsize = 8;  /* Set horizontal and vertical sizes of characters */
  78.   vsize = ((Getrez() == 2)?(16):(8));
  79.   x=50;    /* The window starts with these coordinates */
  80.   y=50;
  81.   w=200;
  82.   h=100;
  83.   set_rsbuf();  /* Set up new RS232 buffer */
  84.   for (;;) {   /* For loop to infinity.... */
  85.     evnt_mesag(msg);  /* Wait for a message */
  86.     if (msg[0] == AC_OPEN)  /* Did someone open our accessory? */
  87.       acc();  /* Yes, go to the main part of the accessory */
  88.     }
  89. }
  90.  
  91. /*
  92.  * This is the main loop in the program.  It handles the window and
  93.  * input and output of characters.
  94.  */
  95. acc()
  96. {
  97.   int msg[8], d, which; /* message buffer, junk variable, 'which' for
  98.                            evnt_multi */
  99.   int i; /* Character accepted */
  100.   int a, j;
  101.   int desel = 0; /* Pseudo-Boolean variable determines whether our window
  102.                     is the active window */
  103.   int dx,dy,dw,dh; /* Temporary variables */
  104.   int stopped = 0; /* Pseudo-Boolean; determines whether output has been
  105.                       stopped with ALT-S */
  106.   long l;
  107.  
  108.   if (init_window() == 0) return; /* If we can't create a window, forget it! */
  109.   align8(&x,&y,&w,&h); /* Make sure the text is on 8-bit boundaries */
  110.   graf_growbox(24,0,56,16,x,y,w,h); /* Growing box */
  111.   wind_open(w_handle,x,y,w,h); /* Open window */
  112.   wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th); /* Get work area */
  113.   nx=tx; /* Set next character's coordinates */
  114.   ny=ty;
  115.   clr(); /* Clear window */
  116.   Cauxout(17); /* Send a CTRL-Q, in case the user deselected the window
  117.                   (sending a CTRL-S) and then ran a program or some such
  118.                   which closed the window */
  119.   for(;;) {
  120.     which = evnt_multi(MU_MESAG|MU_TIMER,0,0,0,0,0,0,0,0,0,0,0,0,0,
  121.                        msg,0,0,&d,&d,&d,&d,&d,&d);
  122.     wind_get(w_handle,WF_TOP,&a,&j,&j,&j); /* Make sure our window is
  123.                                               still on top */
  124.     if ((a != w_handle) && (desel == 0)) {   /* Window has just
  125.                                                 been deselected */
  126.       if (stopped != 1) Cauxout(19); /* Send a CTRL-S */
  127.       desel = 1;
  128.       }
  129.     else
  130.       if ((a == w_handle) && (desel == 1)) { /* Window has just been selected */
  131.         if (stopped != 1) Cauxout(17); /* Send a CTRL-Q */
  132.         desel = 0;
  133.         }
  134.     if ((which & MU_TIMER) && (a == w_handle)) { /* If there are no messages
  135.                                                     and our window is on top */
  136.       if (Bconstat(2)) { /* Is there a character waiting at the keyboard? */
  137.         l = Bconin(2); /* Yes, get it */
  138.         if (l == 2031616L) /* Is it an ALT-S? */
  139.           if (stopped == 0) { /* Yes, is output stopped? */
  140.             Cauxout(19); /* No, stop output and send a CTRL-S */
  141.             stopped = 1;
  142.             }
  143.           else { /* Yes, start output and send a CTRL-Q */
  144.             Cauxout(17);
  145.             stopped = 0;
  146.             }
  147.         if (l == 2162688L) { /* Is the character an ALT-F? */
  148.           toggle_font(); /* Yes, toggle the font size and clear the window */
  149.           clr();
  150.           nx=tx;
  151.           ny=ty;
  152.           }
  153.         Cauxout((int)l); /* Output the character.  If it's ALT-F, a 0 will
  154.                             be output. */
  155.         }
  156.       if (Cauxis() && (stopped == 0)) { /* Is there a character waiting
  157.                                            at the modem port, and is output
  158.                                            enabled? */
  159.         i = Cauxin(); /* Yes.  Get it and output it on the window. */
  160.         MOUSE_OFF;
  161.         outchar(i);
  162.         MOUSE_ON;
  163.         }
  164.       }
  165.     if (which & MU_MESAG) { /* Is there a message for us? */
  166.       switch(msg[0]) { /* Yes, evaluate it */
  167.         case WM_REDRAW : redraw(); /* Redraw the window */
  168.                          nx=tx;
  169.                          ny=ty;
  170.                          break;
  171.         case WM_NEWTOP : /* Top the window that should be on top */
  172.         case WM_TOPPED : wind_set(w_handle,WF_TOP,w_handle,0,0,0);
  173.                          clr();
  174.                          break;
  175.         case AC_OPEN   : form_alert(1,"[1][Window Terminal| |by Matt Kimmel|1987][Okay]");
  176.                          break;  /* Give some credits if someone clicks on our
  177.                                     menu item */
  178.         case AC_CLOSE  : return; /* GEM has closed and deleted our window. */
  179.                          break;
  180.         case WM_CLOSED : wind_close(w_handle);
  181.                          graf_shrinkbox(24,0,56,16,x,y,w,h);
  182.                          wind_delete(w_handle);
  183.                          return; /* The user closed the window.  Close it */
  184.                          break;  /* and delete it */
  185.         case WM_FULLED : full_window(); /* Full the window */
  186.                          break;
  187.         case WM_MOVED  : /* Move the window but make sure the next character
  188.                             output appears after the last, and that the
  189.                             window doesn't go off the screen */
  190.                          wind_get(0,WF_WORKXYWH,&dx,&dy,&dw,&dh);
  191.                          if (((msg[4] + msg[6]) - 1) > ((dx + dw) - 1))
  192.                            msg[4] = ((dx + dw) - 1) - msg[6];
  193.                          if (((msg[5] + msg[7]) - 1) > ((dy + dh) - 1))
  194.                            msg[5] = ((dy + dh) - 1) - msg[7];
  195.                          align8(&msg[4],&msg[5],&msg[6],&msg[7]);
  196.                          nx += (msg[4] - x);
  197.                          ny += (msg[5] - y);
  198.                          x=msg[4];
  199.                          y=msg[5];
  200.                          w=msg[6];
  201.                          h=msg[7];
  202.                          wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  203.                          wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  204.                          break;
  205.         case WM_SIZED  : x=msg[4];  /* Size the window */
  206.                          y=msg[5];
  207.                          w=msg[6];
  208.                          h=msg[7];
  209.                          align8(&x,&y,&w,&h);
  210.                          wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  211.                          wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  212.                          nx=tx;
  213.                          ny=ty;
  214.                          clr();
  215.                          break;
  216.         }
  217.       continue;
  218.       }
  219.     }
  220. }
  221.  
  222. /*
  223.  * Redraw the window.  We are actually just going to wipe all exposed portions
  224.  * of thw window clean.
  225.  */
  226. redraw()
  227. {
  228.   int lx,ly,lw,lh;
  229.   int pxy[4];
  230.   
  231.   vsf_interior(handle,0); /* Set the fill type to the background color */
  232.   MOUSE_OFF;
  233.   wind_update(BEG_UPDATE); /* Don't let the rectangle lists be changed */
  234.   wind_get(w_handle,WF_FIRSTXYWH,&lx,&ly,&lw,&lh); /* Get first rectangle */
  235.   while (lw && lh) {
  236.     pxy[0] = lx;
  237.     pxy[1] = ly;
  238.     pxy[2] = (lx + lw) - 1;
  239.     pxy[3] = (ly + lh) - 1;
  240.     vr_recfl(handle,pxy); /* Wipe this rectangle */
  241.     wind_get(w_handle,WF_NEXTXYWH,&lx,&ly,&lw,&lh); /* Get next rectangle */
  242.     }
  243.   wind_update(END_UPDATE); /* End update */
  244.   MOUSE_ON;
  245. }
  246.  
  247. /*
  248.  * Wipe the entire window clean.  Only works if the window is on top.
  249.  */
  250. clr()
  251. {
  252.   int active;
  253.   int j;
  254.   int p[4];
  255.  
  256.   wind_get(w_handle,WF_TOP,&active,&j,&j,&j); /* Is our window on top? */
  257.   if (active == w_handle) { /* Yes, go ahead */
  258.     wind_get(w_handle,WF_WORKXYWH,&p[0],&p[1],&p[2],&p[3]); /* Get size */
  259.     p[2] += (p[0] - 1);
  260.     p[3] += (p[1] - 1);
  261.     vsf_interior(handle,0); /* Set fill type to background color */
  262.     MOUSE_OFF;    
  263.     vr_recfl(handle,p); /* Wipe the window */
  264.     MOUSE_ON;
  265.     }
  266. }
  267.  
  268. /*
  269.  * This function takes the _outside_ coordinates and size of a window,
  270.  * and changes them so that the inside x and width are divisible by 8.
  271.  * This means that the inside is on an 8-bit boundary, and will speed up
  272.  * scrolling when we use vro_cpyfm().
  273.  */
  274. align8(fx,fy,fw,fh)
  275. int *fx,*fy,*fw,*fh;
  276. {
  277.   int ix,iy,iw,ih;
  278.   
  279.   /* Get inside size of window */
  280.   wind_calc(1,NAME|CLOSE|FULL|MOVE|SIZE,*fx,*fy,*fw,*fh,&ix,&iy,&iw,&ih);
  281.   /* Align it */
  282.   while ((ix % 8) != 0)
  283.     ix++;
  284.   while ((iw % 8) != 0)
  285.     iw++;
  286.   /* Change the aligned inside to an outside size */
  287.   wind_calc(0,NAME|CLOSE|FULL|MOVE|SIZE,ix,iy,iw,ih,fx,fy,fw,fh);
  288. }
  289.  
  290. /*
  291.  * Make the window cover the whole desktop.  Once it's aligned, it will
  292.  * actually leave a little bit of the desktop showing.
  293.  */
  294. full_window()
  295. {
  296.   int jx,jy,jw,jh,fx,fy,fw,fh;
  297.   
  298.   wind_get(w_handle,WF_FULLXYWH,&fx,&fy,&fw,&fh); /* Get the full size */
  299.   if ((x == fx) && (y == fy) && (w == fw) && (h == fh)) {
  300.     /* If it's already fulled, make it smaller.  The smaller one will
  301.        always be aligned already with align8(). */
  302.     wind_get(w_handle,WF_PREVXYWH,&jx,&jy,&jw,&jh); /* Get Previous XYWH */
  303.     graf_shrinkbox(jx,jy,jw,jh,x,y,w,h); /* Shrinking Box */
  304.     x=jx;
  305.     y=jy;
  306.     w=jw;
  307.     h=jh;
  308.     wind_set(w_handle,WF_CURRXYWH,x,y,w,h); /* Set new size and get WORKXYWH */
  309.     wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  310.     nx=tx;
  311.     ny=ty;
  312.     }
  313.   else { /* Otherwise, full it similarly */
  314.     wind_get(w_handle,WF_FULLXYWH,&jx,&jy,&jw,&jh);
  315.     graf_growbox(x,y,w,h,jx,jy,jw,jh);
  316.     x=jx;
  317.     y=jy;
  318.     w=jw;
  319.     h=jh;
  320.     wind_set(w_handle,WF_CURRXYWH,x,y,w,h);
  321.     wind_get(w_handle,WF_WORKXYWH,&tx,&ty,&tw,&th);
  322.     nx=tx;
  323.     ny=ty;
  324.     }
  325.   clr(); /* Clear window */
  326. }
  327.  
  328. /*
  329.  * Create the window.
  330.  */
  331. init_window()
  332. {
  333.   int bx,by,bw,bh;
  334.   
  335.   wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh); /* Get size of desktop for 'FULL'
  336.                                               size. */
  337.   align8(&bx,&by,&bw,&bh); /* Align it */
  338.   bw -= 8; /* Make it fit on the desktop a little better */
  339.   w_handle = wind_create(NAME|CLOSE|FULL|MOVE|SIZE,bx,by,bw,bh); /* Create it */
  340.   if (w_handle < 0) { /* Tell the user if there's an error */
  341.     form_alert(1,"[3][There are no more|windows available!][Sorry!]");
  342.     return (0);
  343.     }
  344.   wind_set(w_handle,WF_NAME," Window Term 1.0-S ",0,0); /* Set window name */
  345.   return(1);
  346. }
  347.  
  348. /*
  349.  * Set the RS232 buffer's information to descrobe our buffer
  350.  */
  351. set_rsbuf()
  352. {
  353.   IORECORD *b;
  354.  
  355.   Cauxout(19);
  356.   b = (IORECORD *)Iorec(0); /* Get pointer to the RS232 buffer descriptor */
  357.   /* Change the descriptor */
  358.   b->ibuf = rs232buf;
  359.   b->ibufsiz = BUFFER_SIZE;
  360.   b->ibuflow = BUFFER_SIZE/4;
  361.   b->ibufhi = BUFFER_SIZE/4*3;
  362.   b->ibufhd = 0;
  363.   b->ibuftl = 0;
  364.   Cauxout(17);
  365. }
  366.  
  367. /*
  368.  * Toggle between the normal and small font
  369.  */
  370. toggle_font()
  371. {
  372.   static int font = 0;
  373.   int j;
  374.  
  375.   if (font == 0) {  /* Change to Icon font */
  376.     vst_point(handle,8,&j,&j,&hsize,&vsize);
  377.     font = 1;
  378.     }
  379.   else {  /* Change to normal font */
  380.     vst_point(handle,((Getrez() == 2)?(10):(9)),&j,&j,&hsize,&vsize);
  381.     font = 0;
  382.     }
  383. }
  384.  
  385. /*
  386.  * Output a character at the next character position in the window
  387.  * using v_gtext
  388.  */
  389. outchar(ch)
  390. int ch;
  391. {
  392.   char str[2];
  393.   int j;
  394.  
  395.   if (ch == 10) {    /* Linefeed */
  396.     /* Put the 'cursor' down one line and scroll if necessary */
  397.     if ((ny + vsize) > ((ty + th) - vsize)) {
  398.       scroll();
  399.       return;
  400.       }
  401.     ny += vsize;
  402.     return;
  403.     }
  404.   if (ch == 13) {    /* Carriage Return */
  405.     /* Put the 'cursor' at the beginning of the line */
  406.     nx = tx;
  407.     return;
  408.     }
  409.   if (ch == 7)  {    /* Bell */
  410.     Bconout(2,7);
  411.     return;
  412.     }
  413.   if (ch == 9) {     /* Tab */
  414.     outchar(32);  /* faster than a for loop */
  415.     outchar(32);
  416.     outchar(32);
  417.     outchar(32);
  418.     outchar(32);
  419.     return;
  420.     }
  421.   if (ch == 12) {    /* Form Feed (clear screen) */
  422.     clr();
  423.     nx=tx;
  424.     ny=ty;
  425.     return;
  426.     }
  427.   if ((ch == 127) || (ch == 8)) {   /* DEL and Backspace */
  428.     /* Put 'cursor' back one space and print a space there */
  429.     if (nx > tx) {
  430.       nx -= hsize;
  431.       v_gtext(handle,nx,ny," ");
  432.       }
  433.     return;
  434.     }
  435.   str[0] = (char)ch; /* Construct a string */
  436.   str[1] = '\0';
  437.   v_gtext(handle,nx,ny,str); /* Output the character */
  438.   nx += hsize; /* Move the cursor to the next space */
  439.   /* If necessary, move the cursor to the next line, and scroll if needed */
  440.   if (nx > ((tx + tw) - hsize)) {
  441.     nx = tx;
  442.     if ((ny + vsize) > ((ty + th) - vsize)) scroll();
  443.     else ny += vsize;
  444.     }
  445. }
  446.  
  447. /*
  448.  * Scroll the contents of the screen up one line using the blit() function
  449.  */
  450. scroll()
  451. {
  452.   int pxy[4];
  453.   
  454.   blit(tx,(ty + vsize),((tx + tw) - 1),(((ty + vsize) + th) - (vsize + 1)),
  455.        tx,ty,((tx + tw) - 1),((ty + th) - (vsize + 1))); /* Call blit() */
  456.   /* clear the bottom line */
  457.   pxy[0] = tx;
  458.   pxy[1] = ny;
  459.   pxy[2] = (tx + tw) - 1;
  460.   pxy[3] = ny + vsize;
  461.   vsf_interior(handle,0);
  462.   vr_recfl(handle,pxy);
  463. }
  464.  
  465. /*
  466.  * Copy the rectangle described by x1,y1,x2,y2 to the rectangle described
  467.  * by x3,y3,x4,y4 using vro_cpyfm()
  468.  */
  469. blit(x1,y1,x2,y2,x3,y3,x4,y4)
  470. int x1,y1,x2,y2,x3,y3,x4,y4;
  471. {
  472.   FDB b;
  473.   int bp[8];
  474.   
  475.   bp[0] = x1;
  476.   bp[1] = y1;
  477.   bp[2] = x2;
  478.   bp[3] = y2;
  479.   bp[4] = x3;
  480.   bp[5] = y3;
  481.   bp[6] = x4;
  482.   bp[7] = y4;
  483.   vro_cpyfm(handle,3,bp,&b,&b);
  484. }
  485.